`include "defines.v"
/*-------------------------*/
/* Just to my beloved Rena */
/*-------------------------*/
module Rena_ooo(
  input clk,
  input rst_n,
  // 用户定义的可屏蔽中断 不影响核心运行的中断
  input user_interrupt,
  // 不可屏蔽的关键中断 例如 UPS断电信号 核心外设错误信号
  input sys_interrupt,
  /* boot  */
  input [`VADDR_W-1:0] boot_addr,
  /* AXI Master */
  /* AR  */
  input                               axi_ar_ready  ,
  output                              axi_ar_valid  ,
  output [`AXI_ADDR_WIDTH-1:0]        axi_ar_addr   ,
  output [2:0]                        axi_ar_prot   ,
  output [`AXI_ID_WIDTH-1:0]          axi_ar_id     ,
  output [`AXI_USER_WIDTH-1:0]        axi_ar_user   ,
  output [7:0]                        axi_ar_len    ,
  output [2:0]                        axi_ar_size   ,
  output [1:0]                        axi_ar_burst  ,
  output                              axi_ar_lock   ,
  output [3:0]                        axi_ar_cache  ,
  output [3:0]                        axi_ar_qos    ,
  /* R */
  output                              axi_r_ready   ,
  input                               axi_r_valid   ,
  input  [1:0]                        axi_r_resp    ,
  input  [`AXI_DATA_WIDTH-1:0]        axi_r_data    ,
  input                               axi_r_last    ,
  input  [`AXI_ID_WIDTH-1:0]          axi_r_id      ,
  input  [`AXI_USER_WIDTH-1:0]        axi_r_user    ,
  /* AW */
  input                               axi_aw_ready  ,       
  output                              axi_aw_valid  ,   
  output [`AXI_ADDR_WIDTH-1:0]        axi_aw_addr   ,   
  output [2:0]                        axi_aw_prot   ,   
  output [`AXI_ID_WIDTH-1:0]          axi_aw_id     ,
  output [`AXI_USER_WIDTH-1:0]        axi_aw_user   ,     
  output [7:0]                        axi_aw_len    ,      
  output [2:0]                        axi_aw_size   ,
  output [1:0]                        axi_aw_burst  ,
  output                              axi_aw_lock   ,   
  output [3:0]                        axi_aw_cache  ,   
  output [3:0]                        axi_aw_qos    ,   
  /* W */
  input                               axi_w_ready   ,  
  output                              axi_w_valid   ,
  output [`AXI_DATA_WIDTH-1:0]        axi_w_data    ,   
  output [`AXI_DATA_WIDTH/8-1:0]      axi_w_strb    ,   
  output                              axi_w_last    ,   
  /* B */
  output                             axi_b_ready   ,
  input                               axi_b_valid   ,
  input  [1:0]                        axi_b_resp    ,  
  input  [`AXI_ID_WIDTH-1:0]          axi_b_id      ,
  input  [`AXI_USER_WIDTH-1:0]        axi_b_user       
);
wire [7:0] debug_a0;
wire externInterrupt = user_interrupt | sys_interrupt;
// IFU to ICache req singal group 
wire                  ifu_icache_valid    ;
wire                  icache_ifu_ready    ;
wire [`VADDR_W-1  :0] ifu_icache_req_addr ;
wire [`BPU_PRE_W-1:0] ifu_icache_predict  ;
// ICache to MMU address translation singal group 
wire                  ifu_mmu_trans_valid ;
wire                  mmu_ifu_trans_ready ;
wire [`VADDR_W-1:0]   ifu_mmu_trans_vaddr ;
wire [`PADDR_W-1:0]   mmu_ifu_trans_paddr ;
// Icache to mem data singal group
wire                  icache_mem_paddr_valid ;
wire [`PADDR_W-1:0]   icache_mem_paddr       ;
wire                  mem_icache_data_valid  ;
wire [511:0]          mem_icache_data        ;
// Icache to IBF instr singal group
wire [4-1:0]          icache_ibf_data_valid ;
wire                  ibf_icache_data_ready ;
wire [`VADDR_W*4-1:0] icache_ibf_vaddr      ;
wire [32*4-1:0]       icache_ibf_instr      ;
wire [`BPU_PRE_W-1:0] icache_ibf_predict    ;
wire [4-1:0]          icache_ibf_usePtr     ;
// // IBF to IDU instr singal group
// wire                  ibf_idu_data_valid ;
// wire                  idu_ibf_data_ready ;
// wire [`VADDR_W-1:0]   ibf_idu_vaddr      ;
// wire [31:0]           ibf_idu_instr      ;
// wire                  ibf_idu_usePtr     ;
// wire [`BPU_PRE_W-1:0] ibf_idu_predict    ;
wire [7:0]  icache_ibf_valid    ;
wire        ibf_icache_ready    ;
wire [15:0] icache_ibf_instIn0  ;
wire [15:0] icache_ibf_instIn1  ;
wire [15:0] icache_ibf_instIn2  ;
wire [15:0] icache_ibf_instIn3  ;
wire [15:0] icache_ibf_instIn4  ;
wire [15:0] icache_ibf_instIn5  ;
wire [15:0] icache_ibf_instIn6  ;
wire [15:0] icache_ibf_instIn7  ;

wire [7:0] ibf_idu_valid ;
wire [2:0] idu_ibf_ready ;
wire [15:0] ibf_idu_instIn0 ;
wire [15:0] ibf_idu_instIn1 ;
wire [15:0] ibf_idu_instIn2 ;
wire [15:0] ibf_idu_instIn3 ;
wire [15:0] ibf_idu_instIn4 ;
wire [15:0] ibf_idu_instIn5 ;
wire [15:0] ibf_idu_instIn6 ;
wire [15:0] ibf_idu_instIn7 ;
// idu
wire ctrl_idu_flush;
wire isu_idu_ready;
wire idu_isu_valid;
wire [`FU_W-1:0]idu_isu_fu;
wire [`OP_W-1:0]idu_isu_op;
wire [4:0] idu_isu_rs1;
wire [4:0] idu_isu_rs2;
wire [4:0] idu_isu_rd;
wire idu_isu_rfwen;
wire [1:0]idu_isu_src1;
wire [1:0]idu_isu_src2;
wire [`XLEN-1:0]idu_isu_imm;
wire [`VADDR_W-1:0]idu_isu_pc;
wire [31:0] idu_isu_inst;
wire [`BPU_PRE_W-1:0]idu_isu_predict;
wire idu_isu_isCps;
// isu
wire ctrl_isu_flush;
wire exu_isu_ready;
wire isu_exu_valid;
wire [`OP_W-1:0]isu_exu_op;
wire [4:0] isu_exu_rd;
wire isu_exu_rfwen;
wire [`XLEN-1:0] isu_exu_op1;
wire [`XLEN-1:0] isu_exu_op2;
wire [`XLEN-1:0] isu_exu_imm;
wire [`ADDR_W-1:0] isu_exu_pc;
wire alu_enable ;
wire aluw_enable;
wire bru_enable ;
wire csr_enable ;
wire lsu_enable ;
wire                 exu_isu_wen  ;  
wire [4:0]           exu_isu_addr ; 
wire [`XLEN-1:0]     exu_isu_data ; 
wire                 wbu_isu_wen  ; 
wire [4:0]           wbu_isu_addr ; 
wire [`XLEN-1:0]     wbu_isu_data ;
wire [31:0]          isu_exu_inst;
wire [`BPU_PRE_W-1:0] isu_exu_predict;
// exu
wire bru_fronted_brunch;
wire ctrl_exu_flush;
wire wbu_exu_ready ;
wire exu_wbu_valid; 
wire exu_wbu_wen;   
wire [4:0]         exu_wbu_rd;    
wire [`XLEN-1:0]   exu_wbu_data;  
wire [`ADDR_W-1:0] exu_wbu_pc;    
wire wr_addr_valid;
wire [`VADDR_W-1:0]wr_addr;
wire [7:0] wr_strb;
wire [127:0]wr_data;
wire wr_data_valid;
wire rd2_addr_valid;
wire [`VADDR_W-1:0]rd2_addr;
wire rd2_data_valid;
wire [127:0]rd2_data;
wire [31:0] exu_wbu_inst;
wire ctrl_wbu_flush;
wire csr_wbu_isClint;
wire [`EXCEPT:0] exu_wbu_exception;
wire             exu_wbu_wr_csr_en;
wire [11:0]      exu_wbu_wr_csr_addr;
wire [`XLEN-1:0] exu_wbu_wr_csr_data;
wire                 exu_wbu_redict_valid;
wire [`VADDR_W-1:0]  exu_wbu_redict_pc   ;
wire [`BRU_MSG_W-1:0]exu_wbu_bru_message ;
wire [11:0]      exu_csr_raddr;
wire [`XLEN-1:0] csr_exu_rdata;
wire             wbu_exu_wr_csr_en  ;
wire [11:0]      wbu_exu_wr_csr_addr;
wire [`XLEN-1:0] wbu_exu_wr_csr_data;
wire             wbu_wr_csr_en; 
wire [`EXCEPT:0] wbu_csr_exception;
wire [11:0]      wbu_wr_csr_addr; 
wire [`XLEN-1:0] wbu_wr_csr_data;  
wire             wbu_csr_commit;
wire clintEn       ;
wire clintInterrupt;
`ifdef DIFFTEST
wire debug_selClint;
`endif
wire  [`VADDR_W-1:0] wbu_csr_pc  ;
wire  [31:0]         wbu_csr_inst;
wire                  csr_wbu_commit_flush;
wire [`VADDR_W-1:0]   csr_wbu_commit_pc   ;
wire                  wbu_ifu_redict_valid;
wire [`VADDR_W-1:0]   wbu_ifu_redict_pc   ;
wire [`BRU_MSG_W-1:0] wbu_ifu_bru_message ;
// DMMU
wire                 exu_mmu_trans_valid;
wire                 mmu_exu_trans_ready;
wire [`VADDR_W-1:0]  exu_mmu_trans_vaddr;
wire [`PADDR_W-1:0]  mmu_exu_trans_paddr;
// LSU 访问的接口
wire lsu_dcache_paddr_valid;
wire [`PADDR_W-1:0]lsu_dcache_paddr;
wire [7:0] lsu_dcache_strb;
wire lsu_dcache_wen;
wire lsu_dcache_invalidate;
wire [63:0] lsu_dcache_wdata;
wire  [63:0] dcache_lsu_rdata;
wire  dcache_lsu_data_valid;
// 下游访问接口 L2Cache 或内存
wire dcache_mem_addr_valid;
wire dcache_mem_wen;
wire [`PADDR_W-1:0] dcache_mem_addr;
wire [511:0] dcache_mem_wdata;
wire [7:0] dcache_mem_strb;
wire mem_dcache_data_valid;
wire [511:0] mem_dcache_rdata;
// 状态控制信号
wire ctrl_icache_flush;
wire ctrl_ibf_flush   ;
wire IcacheInvalidate;
wire idu_stall_i      ;
wire ctrl_ifu_stall   ;
wire ctrl_icache_stall;
wire ctrl_ibf_stall   ;
wire ctrl_idu_stall   ;
wire ctrl_isu_stall   ;
wire ctrl_exu_stall   ;
wire ctrl_wbu_stall   ;

/******************IFU***********************/
ifu IFU(
  .clk         (clk      ),
  .rst_n       (rst_n    ),
  .boot_addr   (boot_addr),
  .stall       (ctrl_ifu_stall),
  
  .redict_valid_i (wbu_ifu_redict_valid),
  .redict_pc_i    (wbu_ifu_redict_pc   ),
  .bru_message    (wbu_ifu_bru_message ),

  .ifu_icache_valid_o    ( ifu_icache_valid    ),
  .icache_ifu_ready_i    ( icache_ifu_ready    ),
  .ifu_icache_req_addr_o ( ifu_icache_req_addr ),
  .ifu_icache_predict_o  ( ifu_icache_predict  )
);  
/******************ICache***********************/
Icache Icache(
  .clk   ( clk              ),
  .rst_n ( rst_n            ),
  .flush ( ctrl_icache_flush),
  .stall ( ctrl_ibf_stall   ),
  .invalidate   (IcacheInvalidate ),
  // request port 
  .ifu_icache_addr_valid_i ( ifu_icache_valid    ),
  .icache_ifu_addr_ready_o ( icache_ifu_ready    ),
  .ifu_icache_vaddr_i      ( ifu_icache_req_addr ),
  .ifu_icache_predict_i    ( ifu_icache_predict  ),
  // MMU address translation
  .icache_mmu_trans_valid_o ( ifu_mmu_trans_valid ),
  .mmu_icache_trans_ready_i ( mmu_ifu_trans_ready ),
  .icache_mmu_trans_vaddr_o ( ifu_mmu_trans_vaddr ),
  .mmu_icache_trans_paddr_i ( mmu_ifu_trans_paddr ),
  // mem port
  .icache_mem_paddr_valid_o ( icache_mem_paddr_valid  ),
  .icache_mem_paddr_o       ( icache_mem_paddr        ),
  .mem_icache_data_valid_i  ( mem_icache_data_valid   ),
  .mem_icache_data_i        ( mem_icache_data         ),
  // resp port
  .icache_ibf_data_valid_o ( icache_ibf_data_valid ),
  .ibf_icache_data_ready_i ( ibf_icache_data_ready ),
  .icache_ibf_vaddr_o      ( icache_ibf_vaddr      ),
  .icache_ibf_instr_o      ( icache_ibf_instr      ),
  .icache_ibf_usePtr_o     ( icache_ibf_usePtr     ),
  .icache_ibf_predict_o    ( icache_ibf_predict    )
);
/******************IBF***********************/
// IBF4In4Out #(
//   .ENTRY_WIDTH(`VADDR_W+32+`BPU_PRE_W+1),
//   .DEPTH(16)
// ) IBF(
//   .clk   (clk           ),
//   .rst_n (rst_n         ),
//   .flush (ctrl_ibf_flush),
//   .stall (ctrl_ibf_stall),

//   .notfull  (ibf_icache_data_ready), 
//   .In0Valid (icache_ibf_data_valid[0]),
//   .In1Valid (icache_ibf_data_valid[1]),
//   .In2Valid (icache_ibf_data_valid[2]),
//   .In3Valid (icache_ibf_data_valid[3]),

//   .In0Entry({icache_ibf_usePtr[0],icache_ibf_predict,icache_ibf_vaddr[`VADDR_W*1-1:`VADDR_W*0],icache_ibf_instr[32*1-1:32*0]}),
//   .In1Entry({icache_ibf_usePtr[1],icache_ibf_predict,icache_ibf_vaddr[`VADDR_W*2-1:`VADDR_W*1],icache_ibf_instr[32*2-1:32*1]}),
//   .In2Entry({icache_ibf_usePtr[2],icache_ibf_predict,icache_ibf_vaddr[`VADDR_W*3-1:`VADDR_W*2],icache_ibf_instr[32*3-1:32*2]}),
//   .In3Entry({icache_ibf_usePtr[3],icache_ibf_predict,icache_ibf_vaddr[`VADDR_W*4-1:`VADDR_W*3],icache_ibf_instr[32*4-1:32*3]}),

//   .useInstNum ({2'b0,idu_ibf_data_ready}),
//   .Out0Valid  (ibf_idu_data_valid),
//   .Out1Valid(),
//   .Out2Valid(),
//   .Out3Valid(),

//   .Out0Entry ({ibf_idu_usePtr,ibf_idu_predict,ibf_idu_vaddr,ibf_idu_instr}),
//   .Out1Entry ('d0),
//   .Out2Entry ('d0),
//   .Out3Entry ('d0)
// );
assign icache_ibf_valid[0] = icache_ibf_data_valid[0] && ~icache_ibf_usePtr[0];
assign icache_ibf_valid[1] = icache_ibf_data_valid[0] ;
assign icache_ibf_valid[2] = icache_ibf_data_valid[1] && ~icache_ibf_usePtr[1];
assign icache_ibf_valid[3] = icache_ibf_data_valid[1] ;
assign icache_ibf_valid[4] = icache_ibf_data_valid[2] && ~icache_ibf_usePtr[2];
assign icache_ibf_valid[5] = icache_ibf_data_valid[2] ;
assign icache_ibf_valid[6] = icache_ibf_data_valid[3] && ~icache_ibf_usePtr[3];
assign icache_ibf_valid[7] = icache_ibf_data_valid[3] ;

assign ibf_icache_data_ready = ibf_icache_ready ;
assign icache_ibf_instIn0  = icache_ibf_instr[16*1-1:16*0];
assign icache_ibf_instIn1  = icache_ibf_instr[16*2-1:16*1];
assign icache_ibf_instIn2  = icache_ibf_instr[16*3-1:16*2];
assign icache_ibf_instIn3  = icache_ibf_instr[16*4-1:16*3];
assign icache_ibf_instIn4  = icache_ibf_instr[16*5-1:16*4];
assign icache_ibf_instIn5  = icache_ibf_instr[16*6-1:16*5];
assign icache_ibf_instIn6  = icache_ibf_instr[16*7-1:16*6];
assign icache_ibf_instIn7  = icache_ibf_instr[16*8-1:16*7];

IBF ibf(
  .clk   (clk           ),
  .rst_n (rst_n         ),
  .flush (ctrl_ibf_flush),

  .icache_ibf_valid_i   ( icache_ibf_valid    ),
  .ibf_icache_ready_o   ( ibf_icache_ready    ),
  .icache_ibf_instIn0_i ( icache_ibf_instIn0  ),
  .icache_ibf_instIn1_i ( icache_ibf_instIn1  ),
  .icache_ibf_instIn2_i ( icache_ibf_instIn2  ),
  .icache_ibf_instIn3_i ( icache_ibf_instIn3  ),
  .icache_ibf_instIn4_i ( icache_ibf_instIn4  ),
  .icache_ibf_instIn5_i ( icache_ibf_instIn5  ),
  .icache_ibf_instIn6_i ( icache_ibf_instIn6  ),
  .icache_ibf_instIn7_i ( icache_ibf_instIn7  ),

  .ibf_idu_valid_o   (ibf_idu_valid   ),
  .idu_ibf_ready_i   (idu_ibf_ready   ),
  .ibf_idu_instIn0_o (ibf_idu_instIn0 ),
  .ibf_idu_instIn1_o (ibf_idu_instIn1 ),
  .ibf_idu_instIn2_o (ibf_idu_instIn2 ),
  .ibf_idu_instIn3_o (ibf_idu_instIn3 ),
  .ibf_idu_instIn4_o (ibf_idu_instIn4 ),
  .ibf_idu_instIn5_o (ibf_idu_instIn5 ),
  .ibf_idu_instIn6_o (ibf_idu_instIn6 ),
  .ibf_idu_instIn7_o (ibf_idu_instIn7 )
);
/******************IDU***********************/
iduHasC IDU(
  .clk                  ( clk              ),
  .rst_n                ( rst_n            ),
  .boot_addr            ( boot_addr        ),
  .ctrl_idu_flush_i     ( ctrl_idu_flush   ),
  .redict_idu_pc_i      ( wbu_ifu_redict_pc),
  .idu_ctrl_stall_o     ( idu_stall        ),
  // ibf in
  .ibf_idu_valid_i      (ibf_idu_valid   ),
  .idu_ibf_ready_o      (idu_ibf_ready   ),
  .ibf_idu_instIn0_i    (ibf_idu_instIn0 ),
  .ibf_idu_instIn1_i    (ibf_idu_instIn1 ),
  .ibf_idu_instIn2_i    (ibf_idu_instIn2 ),
  .ibf_idu_instIn3_i    (ibf_idu_instIn3 ),
  .ibf_idu_instIn4_i    (ibf_idu_instIn4 ),
  .ibf_idu_instIn5_i    (ibf_idu_instIn5 ),
  .ibf_idu_instIn6_i    (ibf_idu_instIn6 ),
  .ibf_idu_instIn7_i    (ibf_idu_instIn7 ),
  // IDU 输出的寄存器信号
  .idu_isu_valid_o      ( idu_isu_valid   ),
  .isu_idu_ready_i      ( isu_idu_ready   ),
  .idu_isu_fu_o         ( idu_isu_fu      ),
  .idu_isu_op_o         ( idu_isu_op      ),
  .idu_isu_rs1_o        ( idu_isu_rs1     ),
  .idu_isu_rs2_o        ( idu_isu_rs2     ),
  .idu_isu_rd_o         ( idu_isu_rd      ),
  .idu_isu_rfwen_o      ( idu_isu_rfwen   ),
  .idu_isu_src1_o       ( idu_isu_src1    ),
  .idu_isu_src2_o       ( idu_isu_src2    ),
  .idu_isu_imm_o        ( idu_isu_imm     ),
  .idu_isu_pc_o         ( idu_isu_pc      ),
  .idu_isu_inst_o       ( idu_isu_inst    ),
  .idu_isu_isCps_o      ( idu_isu_isCps   ),  
  .idu_isu_predict_o    ( idu_isu_predict )
);
/******************ISU***********************/
isu ISU(
  .clk(clk),
  .rst_n(rst_n),
  .ctrl_isu_flush_i(ctrl_isu_flush),

  .idu_isu_valid_i   ( idu_isu_valid    ),
  .isu_idu_ready_o   ( isu_idu_ready    ),
  .idu_isu_fu_i      ( idu_isu_fu       ),
  .idu_isu_op_i      ( idu_isu_op       ),
  .idu_isu_rs1_i     ( idu_isu_rs1      ),
  .idu_isu_rs2_i     ( idu_isu_rs2      ),
  .idu_isu_rd_i      ( idu_isu_rd       ),
  .idu_isu_rfwen_i   ( idu_isu_rfwen    ),
  .idu_isu_src1_i    ( idu_isu_src1     ),
  .idu_isu_src2_i    ( idu_isu_src2     ),
  .idu_isu_imm_i     ( idu_isu_imm      ),
  .idu_isu_pc_i      ( idu_isu_pc       ),
  .idu_isu_inst_i    ( idu_isu_inst     ),
  .idu_isu_predict_i ( idu_isu_predict  ),
  /* common signal*/ 
  .isu_exu_valid_o   ( isu_exu_valid   ),
  .exu_isu_ready_i   ( exu_isu_ready   ),
  .isu_exu_op_o      ( isu_exu_op      ),
  .isu_exu_rd_o      ( isu_exu_rd      ),
  .isu_exu_rfwen_o   ( isu_exu_rfwen   ),
  .isu_exu_op1_o     ( isu_exu_op1     ),
  .isu_exu_op2_o     ( isu_exu_op2     ),
  .isu_exu_imm_o     ( isu_exu_imm     ),
  .isu_exu_pc_o      ( isu_exu_pc      ),
  .isu_exu_inst_o    ( isu_exu_inst    ),
  .isu_exu_predict_o ( isu_exu_predict ),
  /* fu enable signal */
  .alu_enable_o  ( alu_enable  ),
  .aluw_enable_o ( aluw_enable ),
  .mdu_enable_o  ( mdu_enable  ),
  .bru_enable_o  ( bru_enable  ),
  .csr_enable_o  ( csr_enable  ),
  .lsu_enable_o  ( lsu_enable  ),
  /* exu hzard */
  .exu_isu_wen_i   ( exu_isu_wen  ),  
  .exu_isu_addr_i  ( exu_isu_addr ),  
  .exu_isu_data_i  ( exu_isu_data ),  
  /* wb hzard & wen regfile*/
  .wbu_isu_wen_i   ( wbu_isu_wen  ),  
  .wbu_isu_addr_i  ( wbu_isu_addr ),  
  .wbu_isu_data_i  ( wbu_isu_data )
`ifdef DIFFTEST
  ,.debug_a0(debug_a0)
`endif 
);
/******************EXU***********************/
exu EXU(
  .clk(clk),
  .rst_n(rst_n),
  .ctrl_exu_flush_i(ctrl_exu_flush),
  /* isu to exu signal */
  .isu_exu_valid_i   ( isu_exu_valid   ),
  .exu_isu_ready_o   ( exu_isu_ready   ),
  .alu_enable_i      ( alu_enable      ),
  .aluw_enable_i     ( aluw_enable     ),
  .mdu_enable_i      ( mdu_enable      ),
  .bru_enable_i      ( bru_enable      ),
  .csr_enable_i      ( csr_enable      ),
  .lsu_enable_i      ( lsu_enable      ),
  .isu_exu_op_i      ( isu_exu_op      ),
  .isu_exu_rd_i      ( isu_exu_rd      ),
  .isu_exu_rfwen_i   ( isu_exu_rfwen   ),
  .isu_exu_op1_i     ( isu_exu_op1     ),
  .isu_exu_op2_i     ( isu_exu_op2     ),
  .isu_exu_imm_i     ( isu_exu_imm     ),
  .isu_exu_pc_i      ( isu_exu_pc      ),
  .isu_exu_inst_i    ( isu_exu_inst    ),
  .isu_exu_predict_i ( isu_exu_predict ),
  /* exu bypass signal */
  .exu_isu_wen_o   ( exu_isu_wen  ),  
  .exu_isu_addr_o  ( exu_isu_addr ),  
  .exu_isu_data_o  ( exu_isu_data ),
  /* exu to wbu */
  .exu_wbu_valid_o ( exu_wbu_valid ),
  .wbu_exu_ready_i ( wbu_exu_ready ),
  .exu_wbu_wen_o   ( exu_wbu_wen   ),
  .exu_wbu_rd_o    ( exu_wbu_rd    ),
  .exu_wbu_data_o  ( exu_wbu_data  ), 
  .exu_wbu_pc_o    ( exu_wbu_pc    ),
  .exu_wbu_inst_o  ( exu_wbu_inst  ),
  .exu_wbu_exception_o   ( exu_wbu_exception    ),
  .exu_wbu_wr_csr_en_o   ( exu_wbu_wr_csr_en    ),
  .exu_wbu_wr_csr_addr_o ( exu_wbu_wr_csr_addr  ),
  .exu_wbu_wr_csr_data_o ( exu_wbu_wr_csr_data  ),
  .exu_wbu_redict_valid_o( exu_wbu_redict_valid ),
  .exu_wbu_redict_pc_o   ( exu_wbu_redict_pc    ),
  .exu_wbu_bru_message_o ( exu_wbu_bru_message  ),
  /* read csr port */
  .exu_csr_raddr_o ( exu_csr_raddr ),
  .csr_exu_rdata_i ( csr_exu_rdata ),
  /* wbu bypass csr write port */
  .wbu_exu_wr_csr_en_i   ( wbu_exu_wr_csr_en   ),
  .wbu_exu_wr_csr_addr_i ( wbu_exu_wr_csr_addr ),
  .wbu_exu_wr_csr_data_i ( wbu_exu_wr_csr_data ),
  // MMU
  .exu_mmu_trans_valid_o ( exu_mmu_trans_valid ),
  .mmu_exu_trans_ready_i ( mmu_exu_trans_ready ),
  .exu_mmu_trans_vaddr_o ( exu_mmu_trans_vaddr ),
  .mmu_exu_trans_paddr_i ( mmu_exu_trans_paddr ),
  /* MEM 端口*/
  .lsu_dcache_paddr_valid_o ( lsu_dcache_paddr_valid ),
  .lsu_dcache_paddr_o       ( lsu_dcache_paddr       ),
  .lsu_dcache_strb_o        ( lsu_dcache_strb        ),
  .lsu_dcache_wen_o         ( lsu_dcache_wen         ),
  .lsu_dcache_invalidate_o  ( lsu_dcache_invalidate  ),
  .lsu_dcache_wdata_o       ( lsu_dcache_wdata       ),
  .dcache_lsu_rdata_i       ( dcache_lsu_rdata       ),
  .dcache_lsu_data_valid_i  ( dcache_lsu_data_valid  ),
  .clintEn                  ( clintEn                ),
  .clintInterrupt           ( clintInterrupt         )
`ifdef DIFFTEST
  ,
  .debug_selClint           ( debug_selClint         )
`endif
);
/******************WBU***********************/
wbu WBU(
  .clk(clk),
  .rst_n(rst_n),
  .ctrl_wbu_flush_i(ctrl_wbu_flush),
  .exu_wbu_valid_i ( exu_wbu_valid ),
  .wbu_exu_ready_o ( wbu_exu_ready ),
  .exu_wbu_wen_i   ( exu_wbu_wen   ),
  .exu_wbu_rd_i    ( exu_wbu_rd    ),
  .exu_wbu_data_i  ( exu_wbu_data  ), 
  .exu_wbu_pc_i    ( exu_wbu_pc    ),
  .exu_wbu_inst_i  ( exu_wbu_inst  ),
  .exu_wbu_exception_i   ( exu_wbu_exception   ),
  .exu_wbu_wr_csr_en_i   ( exu_wbu_wr_csr_en   ),
  .exu_wbu_wr_csr_addr_i ( exu_wbu_wr_csr_addr ),
  .exu_wbu_wr_csr_data_i ( exu_wbu_wr_csr_data ),
  .exu_wbu_redict_valid_i( exu_wbu_redict_valid),
  .exu_wbu_redict_pc_i   ( exu_wbu_redict_pc   ),
  .exu_wbu_bru_message_i ( exu_wbu_bru_message ),
  /* wbu bypass signal & rf write enable signal*/
  .wbu_isu_wen_o   ( wbu_isu_wen  ),  
  .wbu_isu_addr_o  ( wbu_isu_addr ),  
  .wbu_isu_data_o  ( wbu_isu_data ),
  /* wbu csr bypass to exu */ 
  .wbu_exu_wr_csr_en_o   ( wbu_exu_wr_csr_en   ),
  .wbu_exu_wr_csr_addr_o ( wbu_exu_wr_csr_addr ),
  .wbu_exu_wr_csr_data_o ( wbu_exu_wr_csr_data ),
  /* wbu csr write */
  .wbu_wr_csr_en_o     ( wbu_wr_csr_en     ),
  .wbu_csr_exception_o ( wbu_csr_exception ),
  .wbu_wr_csr_addr_o   ( wbu_wr_csr_addr   ),
  .wbu_wr_csr_data_o   ( wbu_wr_csr_data   ),
  .wbu_csr_pc_o        ( wbu_csr_pc        ),
  .wbu_csr_inst_o      ( wbu_csr_inst      ),
  /* 特殊端口 */
  .wbu_csr_commit_o    ( wbu_csr_commit    ),
  .csr_wbu_isClint_i   ( csr_wbu_isClint   ),
`ifdef DIFFTEST
  .debug_selClint      ( debug_selClint    ),
  .debug_a0            ( debug_a0 ),
`endif
  .csr_wbu_commit_flush_i ( csr_wbu_commit_flush ),
  .csr_wbu_commit_pc_i    ( csr_wbu_commit_pc    ),

  .wbu_ifu_redict_valid_o ( wbu_ifu_redict_valid ),
  .wbu_ifu_redict_pc_o    ( wbu_ifu_redict_pc    ),
  .wbu_ifu_bru_message_o  ( wbu_ifu_bru_message  )
);
/******************CSR***********************/
csr CSR(
  .clk   (clk  ),
  .rst_n (rst_n),
  // 同步写端口
  .wen   ( wbu_wr_csr_en ),
  .waddr ( wbu_wr_csr_addr ),
  .wdata ( wbu_wr_csr_data ),
  // 读端口
  .raddr ( exu_csr_raddr ),
  .rdata ( csr_exu_rdata ),
  // 特殊端口
  .wbu_csr_commit_i    ( wbu_csr_commit             ),
  .wbu_csr_exception_i ( wbu_csr_exception          ),
  .wbu_csr_pc_i        ( wbu_csr_pc                 ),
  .wbu_csr_inst_i      ( wbu_csr_inst               ),
  .clintEn             ( clintEn                    ),
  .clintInterrupt      ( clintInterrupt             ),
  .externInterrupt     ( externInterrupt            ),
  .commit_flush        ( csr_wbu_commit_flush       ),
  .commit_addr         ( csr_wbu_commit_pc          ),
  .commit_invalidate   ( IcacheInvalidate           ),
  .csr_wbu_isClint_o   ( csr_wbu_isClint            )
);
/******************Pipeline***********************/
pipelineControl PipeCtrl(
  .rst_n(rst_n),
  .wbu_redict_valid_i  ( wbu_ifu_redict_valid ),
  .idu_stall_i         ( idu_stall_i       ),
  .ctrl_ifu_stall_o    ( ctrl_ifu_stall    ),
  .ctrl_icache_stall_o ( ctrl_icache_stall ),
  .ctrl_ibf_stall_o    ( ctrl_ibf_stall    ),
  .ctrl_idu_stall_o    ( ctrl_idu_stall    ),
  .ctrl_isu_stall_o    ( ctrl_isu_stall    ),
  .ctrl_exu_stall_o    ( ctrl_exu_stall    ),
  .ctrl_wbu_stall_o    ( ctrl_wbu_stall    ),
  .ctrl_icache_flush_o ( ctrl_icache_flush ),
  .ctrl_ibf_flush_o    ( ctrl_ibf_flush    ),
  .ctrl_idu_flush_o    ( ctrl_idu_flush    ),
  .ctrl_isu_flush_o    ( ctrl_isu_flush    ),
  .ctrl_exu_flush_o    ( ctrl_exu_flush    ),
  .ctrl_wbu_flush_o    ( ctrl_wbu_flush    )
);
/******************MMU***********************/
mmu MMU(
  .clk  (clk  ),
  .rst_n(rst_n),
  // system message
  
  // I MMU 
  .ifu_mmu_trans_valid_i ( ifu_mmu_trans_valid ),
  .mmu_ifu_trans_ready_o ( mmu_ifu_trans_ready ),
  .ifu_mmu_trans_vaddr_i ( ifu_mmu_trans_vaddr ),
  .mmu_ifu_trans_paddr_o ( mmu_ifu_trans_paddr ),
  // D MMU
  .exu_mmu_trans_valid_i ( exu_mmu_trans_valid ),
  .mmu_exu_trans_ready_o ( mmu_exu_trans_ready ),
  .exu_mmu_trans_vaddr_i ( exu_mmu_trans_vaddr ),
  .mmu_exu_trans_paddr_o ( mmu_exu_trans_paddr )
  // Dcache Access

);
/******************Dcache***********************/
Dcache Dcache(
  .clk(clk),
  .rst_n(rst_n),
  .invalidate(1'b0),
  // LSU 访问的接口
  .lsu_dcache_addr_valid_i (lsu_dcache_paddr_valid),
  .lsu_dcache_addr_i       (lsu_dcache_paddr      ),
  .lsu_dcache_strb_i       (lsu_dcache_strb       ),
  .lsu_dcache_wen_i        (lsu_dcache_wen        ),
  .lsu_dcache_invalidate_i (lsu_dcache_invalidate ),
  .lsu_dcache_wdata_i      (lsu_dcache_wdata      ),
  .dcache_lsu_rdata_o      (dcache_lsu_rdata      ),
  .dcache_lsu_data_valid_o (dcache_lsu_data_valid ),
  // 下游访问接口 L2Cache 或内存
  .dcache_mem_addr_valid_o (dcache_mem_addr_valid ),
  .dcache_mem_wen_o        (dcache_mem_wen        ),
  .dcache_mem_addr_o       (dcache_mem_addr       ),
  .dcache_mem_wdata_o      (dcache_mem_wdata      ),
  .mem_dcache_data_valid_i (mem_dcache_data_valid ),
  .mem_dcache_rdata_i      (mem_dcache_rdata      )
);
/******************TO AXI***********************/
biu BIU(
  .clk(clk),
  .rst_n(rst_n),

  .icache_mem_addr_valid_i ( icache_mem_paddr_valid ),
  .icache_mem_addr_i       ( icache_mem_paddr       ),
  .mem_icache_data_valid_o ( mem_icache_data_valid  ),
  .mem_icache_data_o       ( mem_icache_data        ),

  .dcache_mem_addr_valid_i (dcache_mem_addr_valid ),
  .dcache_mem_wen_i        (dcache_mem_wen        ),
  .dcache_mem_addr_i       (dcache_mem_addr       ),
  .dcache_mem_wdata_i      (dcache_mem_wdata      ),
  .dcache_mem_strb_i       (lsu_dcache_strb       ),
  .mem_dcache_data_valid_o (mem_dcache_data_valid ),
  .mem_dcache_rdata_o      (mem_dcache_rdata      ),
 
  .axi_aw_ready      (axi_aw_ready),       
  .axi_aw_valid      (axi_aw_valid),   
  .axi_aw_bits_addr  (axi_aw_addr ),   
  .axi_aw_bits_prot  (axi_aw_prot ),   
  .axi_aw_bits_id    (axi_aw_id   ),
  .axi_aw_bits_user  (axi_aw_user ),     
  .axi_aw_bits_len   (axi_aw_len  ),      
  .axi_aw_bits_size  (axi_aw_size ),
  .axi_aw_bits_burst (axi_aw_burst),
  .axi_aw_bits_lock  (axi_aw_lock ),   
  .axi_aw_bits_cache (axi_aw_cache),   
  .axi_aw_bits_qos   (axi_aw_qos  ),   
  
  .axi_w_ready     (axi_w_ready) ,  
  .axi_w_valid     (axi_w_valid) ,
  .axi_w_bits_data (axi_w_data ) ,   
  .axi_w_bits_strb (axi_w_strb ) ,   
  .axi_w_bits_last (axi_w_last ) ,   
  
  .axi_b_ready     (axi_b_ready ),
  .axi_b_valid     (axi_b_valid ),
  .axi_b_bits_resp (axi_b_resp  ),  
  .axi_b_bits_id   (axi_b_id    ),
  .axi_b_bits_user (axi_b_user  ),
  
  .axi_ar_ready      (axi_ar_ready ),
  .axi_ar_valid      (axi_ar_valid ),
  .axi_ar_bits_addr  (axi_ar_addr  ),
  .axi_ar_bits_prot  (axi_ar_prot  ),
  .axi_ar_bits_id    (axi_ar_id    ),
  .axi_ar_bits_user  (axi_ar_user  ),
  .axi_ar_bits_len   (axi_ar_len   ),
  .axi_ar_bits_size  (axi_ar_size  ),
  .axi_ar_bits_burst (axi_ar_burst ),
  .axi_ar_bits_lock  (axi_ar_lock  ),
  .axi_ar_bits_cache (axi_ar_cache ),
  .axi_ar_bits_qos   (axi_ar_qos   ),

  .axi_r_ready     (axi_r_ready ),
  .axi_r_valid     (axi_r_valid ),
  .axi_r_bits_resp (axi_r_resp  ),
  .axi_r_bits_data (axi_r_data  ),
  .axi_r_bits_last (axi_r_last  ),
  .axi_r_bits_id   (axi_r_id    ),
  .axi_r_bits_user (axi_r_user  ) 
);
  
endmodule
